#include "Sphere.h"
#define _USE_MATH_DEFINES
#include <math.h>


Sphere::Sphere(Point& pos,float R)
{
	this->pos = pos;	
	this->_R = R;
	this->texture = NULL;
	calcVertex(10,10);
}

void Sphere::calcVertex(int vN,int aN)
{
	_vN = vN;_aN = aN;

	int vCnt = 0,aCnt = 0;
	_N = vN * aN * 2;
	this->tris = new Traingle[_N];

	int i;
	float z,z1,absz,absz1,r,r1,a,a1;

	int k = 0;
	printf("Sphere$\n");
	for (int vCnt = 0; vCnt < vN; ++vCnt)
	{
		for(int aCnt = 0; aCnt < aN; ++aCnt){
			i = vCnt * aN * 2 + aCnt * 2;
			z = pos.z - _R + (2.0f * _R / (vN)) * vCnt;
			z1 = pos.z - _R + (2.0f * _R / (vN)) * (vCnt + 1);
			absz = abs(z - pos.z);
			absz1 = abs(z1 - pos.z);
			r = sqrtf(_R * _R - absz * absz);
			r1 = sqrtf(_R * _R - absz1 * absz1);
			//printf("r:%f\tabsz:%f\tz:%f\n",r,absz,z);
			a = (float)aCnt / (aN) * M_PI * 2.0f;
			a1 = float(aCnt + 1) / (aN) * M_PI * 2.0f;
			{
				tris[i].p[0].z = z ;
				tris[i].p[1].z = tris[i].p[2].z = z1 ;
				tris[i].p[0].x = r * cosf(a) + pos.x;
				tris[i].p[1].x = r * cosf(a1) + pos.x;
				tris[i].p[2].x = r1 * cosf(a) + pos.x;
				tris[i].p[0].y = r * sinf(a) + pos.y;;
				tris[i].p[1].y = r * sinf(a1) + pos.y;
				tris[i].p[2].y = r1 * sinf(a) + pos.y;
				if (texture)
				{
					float u1,v1,u2,v2;
					u1 = a / (2.0f * M_PI); 
					v1 = acosf((z - pos.z)/_R) / (1.0f * M_PI);
					u2 = a1 / (2.0f * M_PI); 
					v2 = acosf((z1 - pos.z)/_R) / (1.0f * M_PI);
					tris[i].setTexture(texture,Vec3(u1,v1),Vec3(u2,v2),Vec3(u1,v2));
					printf("[1]%f,%f$%f,%f\n",u1,v1,u2,v2);
				}
			}
			{
				tris[i+1].p[0].z = tris[i+1].p[1].z = z ;
				tris[i+1].p[2].z = z1 ;
				tris[i+1].p[0].x = r * cosf(a) + pos.x;
				tris[i+1].p[1].x = r * cosf(a1) + pos.x;
				tris[i+1].p[2].x = r1 * cosf(a1) + pos.x;
				tris[i+1].p[0].y = r * sinf(a) + pos.y;
				tris[i+1].p[1].y = r * sinf(a1) + pos.y;;
				tris[i+1].p[2].y = r1 * sinf(a1) + pos.y;;
				if (texture)
				{
					float u1,v1,u2,v2;
					u1 = a / (2.0f * M_PI); 
					v1 = acosf((z - pos.z)/_R) / (1.0f * M_PI);
					u2 = a1 / (2.0f * M_PI); 
					v2 = acosf((z1 - pos.z)/_R) / (1.0f * M_PI);
					tris[i+1].setTexture(texture,Vec3(u1,v1),Vec3(u2,v1),Vec3(u2,v2));
					printf("[2]%f,%f$%f,%f\n",u1,v1,u2,v2);
				}
			}
			k += 2;
		}
	}
}

Sphere::~Sphere(void)
{
}

void Sphere::draw(IPixelDrawer* dr) {
	for (int i = 0 ;i < _N; ++i)
	{
		tris[i].draw(dr);
	}
}

void Sphere::setShowBorder(bool b){
	for (int i = 0 ;i < _N; ++i)
	{
		tris[i].setShowBorder(b);
	}
	IPrimitive::setShowBorder(b);
}

void Sphere::mulMat(Mat4& mat)
{
	for (int i = 0 ;i < _N; ++i)
	{
		tris[i].mulMat(mat);
	}
}

void Sphere::setTexture(Texture* texture)
{
	this->texture = texture;
	if (tris)
	{
		delete []tris;
		tris = NULL;
	}
	calcVertex(_vN,_aN);
}


